import {Injectable} from '@angular/core';
import {DocMenu} from '../entity/doc-menu';
import {TpStorageService} from './tp-storage.service';
import {TpHttpService} from './tp-http.service';
import {Artifact} from '../entity/artifact';
import {BehaviorSubject, Observable} from 'rxjs';
import {tap} from 'rxjs/internal/operators';
import {PageVoService} from './page-vo.service';
import {Menu} from '../entity/menu';
import {UserService} from './user.service';
import {DocFocusService} from './doc-focus.service';
import {MenuService} from './menu.service';

@Injectable({
    providedIn: 'root'
})
export class DocIndexService {
    private static DOC_LIST_KEY = 'docs';

    /**
     * 置顶的文档
     */
    private topMenuIds: string[];

    private docs: Artifact[];

    constructor(private httpService: TpHttpService,
                private pageVoService: PageVoService,
                private docFocusService: DocFocusService,
                private tpStorageService: TpStorageService,
                private userService: UserService,
                private menuService: MenuService) {
    }

    public getDocList(): Observable<Artifact[]> {
        let docs: Artifact[] = this.docs;
        if (docs) {
            return new Observable<Artifact[]>(observer => observer.next(docs));
        }

        if (!docs) {
            docs = this.tpStorageService.getObj(DocIndexService.DOC_LIST_KEY);
        }
        if (docs) {
            let lastDocVersion = 0;
            docs.forEach(doc => {
                lastDocVersion = Math.max(doc.docVersion, lastDocVersion);
            });
            this.checkDocList(lastDocVersion);
            return new Observable<Artifact[]>(observer => observer.next(docs));
        }
        return this.httpService.get('/api/doc/docs')
            .pipe(
                tap((data: Artifact[]) => {
                    this.tpStorageService.set(DocIndexService.DOC_LIST_KEY, JSON.stringify(data));
                })
            );
    }

    public setDocFocus(menu: DocMenu) {
        if (!this.topMenuIds) {
            this.topMenuIds = this.docFocusService.getFocusDocIds();
        }
        if (menu.top) {
            this.topMenuIds.push(menu.id);
        } else {
            this.topMenuIds.forEach(docId => {
                if (docId === menu.id) {
                    this.topMenuIds = this.topMenuIds.filter(item => docId !== item);
                }
            });
        }
        this.tpStorageService.set(TpStorageService.KEY_MY_FOCUS, JSON.stringify(this.topMenuIds));

        // 更新菜单
        this.updateDocListMenu(this.docs);

        if (!this.userService.getUser()) {
            return;
        }
        // 保存
        if (menu.top) {
            // 关注
            this.docFocusService.focus(menu.id);
        } else {
            // 取消关注
            this.docFocusService.unfocus(menu.id);
        }
    }

    search(keyword: string): Observable<Menu[]> {
        const searchObservable = new BehaviorSubject<Menu[]>([]);

        this.getDocList().subscribe(artifacts => {
            if (!artifacts) {
                searchObservable.next([]);
                return;
            }

            const matchedDocs: Artifact[] = [];
            artifacts.forEach((artifact, index) => {
                if (this.checkDocMatched(artifact, keyword)) {
                    matchedDocs.push(artifact);
                }
            });
            const menus = this.menuService.getDocIndexLeftMenus(matchedDocs, this.getOwnDocs());
            searchObservable.next(menus);
        });
        return searchObservable;
    }

    public updateDocListMenu(docs: Artifact[]) {
        this.docs = docs;
        const pageVo = this.pageVoService.getPageVo();

        pageVo.leftMenus = this.menuService.getDocIndexLeftMenus(docs, this.getOwnDocs());
        pageVo.leftMenuId = 'index';
        this.pageVoService.setPageVo(pageVo);
    }

    private getOwnDocs(): string[] {
        const user = this.userService.getUser();
        if (!user) {
            return [];
        }
        return user.docsOwner;
    }

    private checkDocMatched(artifact: Artifact, keyword: string): boolean {
        let index = artifact.artifactId.indexOf(keyword);
        if (index !== -1) {
            return true;
        }

        if (artifact.name) {
            index = artifact.name.indexOf(keyword);
            if (index !== -1) {
                return true;
            }
        }

        if (artifact.description) {
            index = artifact.description.indexOf(keyword);
            if (index !== -1) {
                return true;
            }
        }

        return false;
    }

    private checkDocList(lastDocVersion: number) {
        this.httpService.get('/api/doc/docs-check?v=' + lastDocVersion)
            .subscribe((data: Artifact[]) => {
                if (!data) {
                    return;
                }

                this.tpStorageService.set(DocIndexService.DOC_LIST_KEY, JSON.stringify(data));
                // 更新左菜单
                this.updateDocListMenu(data);
            });
    }
}
